package com.cryptoneedle.garden.service.garden.source.constraint;


import com.bubbles.engine.data.core.repository.BaseRepository;
import com.bubbles.engine.data.core.service.BaseService;
import com.cryptoneedle.garden.entity.source.constraint.SourceIndexUnique;
import com.cryptoneedle.garden.entity.source.metadata.SourceCatalog;
import com.cryptoneedle.garden.entity.source.metadata.SourceDatabase;
import com.cryptoneedle.garden.key.source.constraint.IndexKey;
import com.cryptoneedle.garden.repository.source.constraint.SourceIndexUniqueRepository;
import com.cryptoneedle.garden.service.crud.garden.source.*;
import com.cryptoneedle.garden.service.util.JdbcUtil;
import com.google.common.collect.Maps;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>description: 源数据源-唯一索引 </p>
 *
 * @author CryptoNeedle
 * @date 2025-06-20
 */
@Slf4j
@Service
public class IndexUniqueService extends BaseService<SourceIndexUnique, IndexKey> {

    @Resource
    private IndexUniqueService indexUniqueService;
    @Resource
    private SourceIndexUniqueRepository sourceIndexUniqueRepository;

    @Override
    public BaseRepository<SourceIndexUnique, IndexKey> getRepository() {
        return this.sourceIndexUniqueRepository;
    }

    @Autowired
    private  FoundSourceService select;
    @Autowired
    private AddSourceService add;
    @Autowired
    private PatchSourceService patch;
    @Autowired
    private SaveSourceService save;
    @Autowired
    private DeleteSourceService delete;

    public void syncDatabase(SourceCatalog catalog, SourceDatabase database) {
        JdbcTemplate jdbcTemplate = JdbcUtil.getJdbcTemplate(catalog);
        List<SourceIndexUnique> indexUniques = jdbcTemplate.query(catalog
                .getDatabaseType()
                .getDatabase()
                .getIndexUniqueSql(database.getDatabaseName()), (resultSet, rowNum) -> {
            SourceIndexUnique indexUnique = new SourceIndexUnique()
                    .setCatalogName(database.getCatalogName())
                    .setDatabaseName(database.getDatabaseName())
                    .setTableName(resultSet.getString("tableName"))
                    .setIndexName(resultSet.getString("indexName"))
                    .setColumnName(resultSet.getString("columnName"))
                    .setColumnExpression(resultSet.getString("columnExpression"))
                    .setPosition(resultSet.getInt("position"));
            return indexUnique;
        });

        indexUniqueService.compareData(database, indexUniques);
    }

    @Transactional
    public void compareData(SourceDatabase database, List<SourceIndexUnique> dealList) {
        List<SourceIndexUnique> originList = select.indexUniques(database);
        // 已存在
        Map<String, SourceIndexUnique> originMap = Maps.uniqueIndex(originList, origin -> origin.indexUniqueKey().toString());
        // 待处理
        Map<String, SourceIndexUnique> dealMap = Maps.uniqueIndex(dealList, deal -> deal.indexUniqueKey().toString());

        // 新增
        List<SourceIndexUnique> extraList = dealList.stream().filter(deal -> !originMap.containsKey(deal.indexUniqueKey().toString())).toList();

        // 保存
        List<SourceIndexUnique> existsList = originList.stream().filter(origin -> dealMap.containsKey(origin.indexUniqueKey().toString())).peek(origin -> {
            SourceIndexUnique deal = dealMap.get(origin.indexUniqueKey().toString());
            origin.setColumnExpression(deal.getColumnExpression());
            origin.setPosition(deal.getPosition());
        }).toList();

        // 移除
        List<SourceIndexUnique> missList = originList.stream().filter(item -> !dealMap.containsKey(item.indexUniqueKey().toString())).toList();

        add.indexUniques(extraList);
        save.indexUniques(existsList);
        delete.indexUniques(missList);

        log.info("[SYNC] {} -> {} -> 元数据采集 -> Unique  Index      => 共计{} | 新增{} | 删除{}", database.getCatalogName(), database.getDatabaseName(), String.format("%5d", dealList.size()), String.format("%5d", extraList.size()), String.format("%5d", missList.size()) + (
                !missList.isEmpty() ? " => " + missList
                        .stream()
                        .map(indexUnique -> indexUnique.getTableName() + " - " + indexUnique.getIndexName())
                        .collect(Collectors.joining(",")) : ""));
    }
}